import logging
import requests
import json
from datetime import datetime
from django.conf import settings
from common.const import IntervalType
from api.external.dwc import DWC_CHINESE_NAME_MAPPER
from common.utils.db import list_object
from event_rule.agent.agent_platform_rule.custom_service_analysis import CUSTOM_SERVICE_ANALYSIS_CONFIG
from common.es_core.report_creator import (
    ReportCreator,
    get_daily_first_recharge
)
from common.es_core.es_interface import es_search_interface
from event_rule.dwc.agent_event.agent_chn_analysis import (
    AGENT_CHN_BALANCE_CONFIG
)
from event_rule.dwc.agent_event.financial_report import (
    FINANCIAL_REPORT_CONFIG
)
from preprocessor.dwc.model_router import ACCOUNT_MODEL_ROUTER
from common.dwc import shared_handler
from common.mg_core.mg import get_report_template

_LOGGER = logging.getLogger(__name__)

## 雙向稅收配置
PLATFORM_TAX_ADJUSTMENT = {
    'tt': {
        'ttby': {'target_key': 'bet_amount', 'ratio': 0.015},
        'shz': {'target_key': 'bet_amount', 'ratio': 0.025},
        'zjh': {'target_key': 'bet_amount', 'ratio': 0.025},
        'qznn': {'target_key': ['award_amount', 'tax_amount'], 'ratio': 0.025},
        'ermj': {'target_key': ['award_amount', 'tax_amount'], 'ratio': 0.025},
        'xzmj': {'target_key': ['award_amount', 'tax_amount'], 'ratio': 0.025}
    },
    'dark3': {
        'fish': {'target_key': 'bet_amount', 'ratio': 0.015}
    },
    'dark4': {
        'fish': {'target_key': 'bet_amount', 'ratio': 0.015}
    },
    'dark2': {
        'fish': {'target_key': 'bet_amount', 'ratio': 0.02},
        'hero': {'target_key': 'bet_amount', 'ratio': 0.02}
    }
}


def _adjust_agent_balance_tax(platform_id, chn_list, time_range, calc_new_user=None):
    query_dsl = {
        "query": {
            "bool": {
                "filter": [
                    {"term": {"_event_id": "bet_order"}},
                    {"bool": {"should": [{"terms": {"_chn": chn_list}},
                                         {"terms": {"_agent_chn": chn_list}}]}},
                    {"range": {"_event_time": {
                        "gte": int(time_range[0].timestamp()),
                        "lt": int(time_range[1].timestamp())
                    }}},
                    {"term": {"bet_order_user_type": 0}},
                ],
                "must_not": [{"term": {"bet_order_no_limit_room": 1}}]
            }
        },
        "size": 100000
    }
    if calc_new_user:
        query_dsl['query']['bool']['filter'] += [{"term": {"_is_new_user": 1}}]
    res = es_search_interface(platform_id, query_dsl)
    tax_dct = {}
    platform_tax_adjustment = PLATFORM_TAX_ADJUSTMENT.get(platform_id, {})
    for item in res['hits']['hits']:
        item_source = item['_source']
        if item_source['bet_order_sub_type'] not in platform_tax_adjustment:
            tax_dct.setdefault(item_source['bet_order_sub_type'], 0)
            tax_dct[item_source['bet_order_sub_type']] += item_source['bet_order_tax_amount']
        else:
            target_key = platform_tax_adjustment[item_source['bet_order_sub_type']]['target_key']
            base_amount = 0
            if isinstance(target_key, list):
                for key in target_key:
                    base_amount += item_source['_'.join(['bet_order', key])]
                base_amount = abs(base_amount)
            else:
                base_amount = abs(item_source['_'.join(['bet_order', target_key])])
            ratio = platform_tax_adjustment[item_source['bet_order_sub_type']]['ratio']
            tax = base_amount * float(ratio)
            tax_dct.setdefault(item_source['bet_order_sub_type'], 0)
            tax_dct[item_source['bet_order_sub_type']] += tax
    return [{"key": key, "sum": value} for key, value in tax_dct.items()]


def _get_agent_first_recharge_day_total_recharge(platform_id, chn_list, time_range):
    first_recharge_day_total_recharge = 0
    first_recharge_day_user_count = 0
    first_recharge_day_total_recharge_query_dsl = {
        "query": {
            "bool": {
                "filter": [
                    {"term": {"_chn": chn_list}},
                    {"term": {"_event_id": "recharge"}}
                ]
            }
        },
        "aggs": {
            "user_recharge_detail": {
                "terms": {
                    "field": "user_id",
                    "size": 10000
                },
                "aggs": {
                    "previous_recharge": {
                        "filter": {"range": {"_event_time": {"lt": time_range[0]}}},
                        "aggs": {
                            "_previous_recharge": {"sum": {"field": "recharge_price"}}
                        }
                    },
                    "today_recharge": {
                        "filter": {"range": {"_event_time": {"gte": time_range[0], "lt": time_range[1]}}},
                        "aggs": {
                            "_today_recharge": {"sum": {"field": "recharge_price"}}
                        }
                    }
                }
            }
        }
    }
    res_json = es_search_interface(platform_id, first_recharge_day_total_recharge_query_dsl)
    buckets = res_json.get('aggregation', {}).get('buckets', [])
    for bucket in buckets:
        if not bucket.get('previous_recharge', {}).get('_previous_recharge', 0) > 0:
            first_recharge_day_total_recharge += bucket.get('total_recharge', {}).get('_total_recharge', 0)
            first_recharge_day_user_count += 1
    return first_recharge_day_total_recharge, first_recharge_day_user_count


def agent_balance_report_handler(platform_id, chn_list, time_range, calc_new_user):
    _filter = {"should": [
        {"terms": {"_chn": chn_list}},
        {"terms": {"_agent_chn": chn_list}}
    ]}
    custom_filter = [
        {"bool": _filter},
        {"range": {"_event_time": {"gte": int(time_range[0].timestamp()), "lt": int(time_range[1].timestamp())}}}
    ]
    if calc_new_user:
        custom_filter += [{"term": {"_is_new_user": 1}}]
    not_filter = [{"term": {"bet_order_no_limit_room": 1}}]
    base_query = {"query": {"bool": {"filter": custom_filter, "must_not": not_filter}}}
    res = es_search_interface(index=platform_id, es_dsl=base_query)
    if res['hits']['total'] == 0:
        return {"active_count": 0, "register_count": 0, "total_recharge": 0.0, "total_withdraw": 0.0,
                "recharge_user": 0,
                "recharge_count": 0, "withdraw_count": 0, "agency_recharge": 0.0, "tax_buckets": []}
    res = ReportCreator.create_report(start_time=time_range[0], end_time=time_range[1],
                                      event_rule=AGENT_CHN_BALANCE_CONFIG, index=platform_id,
                                      custom_filter=custom_filter)
    if platform_id in PLATFORM_TAX_ADJUSTMENT:
        res['tax_buckets'] = _adjust_agent_balance_tax(platform_id, chn_list, time_range, calc_new_user)
    return res


def _adjust_tax_list_tax(platform_id, tax_item):
    platform_tax_adjustment = PLATFORM_TAX_ADJUSTMENT.get(platform_id, {})
    if tax_item['tax_game_id'] not in platform_tax_adjustment:
        return tax_item
    target_key = platform_tax_adjustment[tax_item['bet_order_sub_type']]['target_key']
    ratio = platform_tax_adjustment[tax_item['bet_order_sub_type']]['ratio']
    if isinstance(target_key, list):
        base_amount = 0
        for key in target_key:
            base_amount += tax_item['_'.join(['bet_order', key])]
        base_amount = abs(base_amount)
    else:
        base_amount = abs(tax_item['_'.join(['bet_order', target_key])])
    tax_item['tax_tax'] = base_amount * float(ratio)
    return tax_item


def get_tax_list(platform_id, chn_list, timestamp, user_id, size):
    query_dsl = {
        "size": size,
        "query": {
            "bool": {
                "filter": [
                    {"term": {"_event_id": "bet_order"}},
                    {"term": {"bet_order_user_type": 0}}
                ],
                "must_not": [{"term": {"bet_order_no_limit_room": 1}}]
            }
        },
        "sort": [
            {"_event_time": "asc"},
            {"_user_id": {"order": "desc"}}
        ]
    }
    if chn_list:
        query_dsl["query"]["bool"]["filter"] += [{"bool": {"should": [{"terms": {"_chn": chn_list}},
                                                                      {"terms": {"_agent_chn": chn_list}}]}}]
    if timestamp and user_id:
        query_dsl["search_after"] = [timestamp, user_id]
    resp_json = es_search_interface(platform_id, query_dsl)
    result_list = []
    hits = resp_json.get('hits', {})
    for item in hits.get('hits', []):
        item_source = item['_source']
        if item_source.get('_agent_chn'):
            item_source['_chn'] = item_source['_agent_chn']
        item_source['tax_game_id'] = item_source['bet_order_sub_type']
        item_source['tax_tax'] = item_source['bet_order_tax_amount']
        if platform_id in PLATFORM_TAX_ADJUSTMENT:
            item_source = _adjust_tax_list_tax(platform_id, item_source)
        if item_source['tax_tax'] > 0:
            result_list.append(item_source)
        user_id, timestamp = item_source['_user_id'], item_source['_event_time']
    if not result_list and len(hits.get('hits', [])) != 0:
        _LOGGER.info('no available tax detail exists, do again')
        return get_tax_list(platform_id, chn_list, timestamp, user_id, size)
    return dict(items=result_list, total=hits.get('total', 0), user_id=user_id, timestamp=timestamp)


def get_user_info(user_id, phone, chn, children_chn):
    tables_to_search = ACCOUNT_MODEL_ROUTER
    query_dct = dict({})
    if user_id:
        query_dct['user_id'] = int(user_id)
    if phone:
        query_dct['phone'] = phone
    if chn:
        query_dct['channel'] = chn
    if children_chn:
        query_dct['channel__in'] = children_chn
    resp_items = []
    for platform_id, table in tables_to_search.items():
        users_list, _ = list_object(query_dct, table, disable_paginate=True)
        for user in users_list:
            resp_items.append(dict(platform_name=DWC_CHINESE_NAME_MAPPER.get(platform_id, platform_id),
                                   chn=user['channel'], phone=user.get('phone'), _id=user['user_id']))
    return resp_items


def get_custom_service_report(agent_id_list):
    custom_filter = [{"terms": {"_agent_id": agent_id_list}}]
    result = ReportCreator.create_report(
        start_time=datetime(2019, 1, 1), end_time=datetime.now(), event_rule=CUSTOM_SERVICE_ANALYSIS_CONFIG,
        index='agent', custom_filter=custom_filter, to_group=True
    )
    result = {int(report['_agent_id']): report for report in result['list']}
    return result


def manual_bind_chn(platform_id, user_id, agent_chn):
    shared_handler.manual_bind_appid(platform_id, user_id, shared_handler.MarketingPlatformType.AGENT, agent_chn)


def get_user_agent_chn(platform_id, user_id):
    return shared_handler.get_user_channel_for_marketing_platform(
        platform_id, user_id, shared_handler.MarketingPlatformType.AGENT)


def get_financial_chn_report(index, time_range):
    start_time, end_time = time_range[0], time_range[1]
    day = str(start_time).split(' ')[0]
    res = requests.get(settings.AGENT_CHANNEL_LIST_API)
    bind_chn_pool = json.loads(res.content)['data']['chn']
    index_bind_chn = bind_chn_pool.get(settings.AGENT_INDEX_MAP[index], [])
    custom_filter = [{"terms": {"_chn.keyword": index_bind_chn}}]
    dynamic_target_users_dct = get_daily_first_recharge(index, start_time, end_time)
    chn_reports = ReportCreator.create_report(start_time=start_time, end_time=end_time,
                                              event_rule=FINANCIAL_REPORT_CONFIG, index=index,
                                              custom_filter=custom_filter,
                                              dynamic_argument_dct=dynamic_target_users_dct, to_group=True)
    resp_items = list()
    for report in chn_reports['list']:
        report_id = '-'.join([report[FINANCIAL_REPORT_CONFIG.get('group_by').replace('.keyword', '')], day])
        report_template = get_report_template(start_time, IntervalType.DAY, custom_report_id=report_id)
        report_template.update(report)
        resp_items.append(report_template)
    return resp_items
